package dao

import (
	"context"
	"crypto/md5"
	"errors"
	"fmt"
	"github.com/go-redis/redis/v8"
	"github.com/golang-jwt/jwt/v4"
	"gorm.io/gorm"
	"icasset/internal/data"
	"icasset/internal/model"
	"log"
	"strconv"
	"time"
)

type GormUserDAO struct {
	ctx   context.Context
	redis *redis.Client
	db    *gorm.DB
}

func NewGormUserDAO(db *gorm.DB) *GormUserDAO {
	return &GormUserDAO{
		db:    db,
		redis: data.InitRedisClient(),
		ctx:   context.Background(),
	}
}

func (dao *GormUserDAO) AddUser(user *model.User) error {
	//return dao.data.WithContext(ctx).Create(user).Error
	// 检查用户是否已存在
	err := dao.db.AutoMigrate(&model.User{})
	if err != nil {
		log.Fatalf("Failed to auto-migrate database: %v", err)
	}

	var existingUser model.User
	err = dao.db.Where("email = ?", user.Email).First(&existingUser).Error
	if err == nil {
		return errors.New("user already exists")
	}
	return dao.db.Create(user).Error
}

func (dao *GormUserDAO) GetAllUsers() ([]*model.User, error) {
	var users []*model.User
	err := dao.db.Find(&users).Error
	if err != nil {
		return nil, err
	}
	return users, nil
}

func (dao *GormUserDAO) Register(user *model.User) error {
	// 检查用户是否已存在
	var existingUser model.User
	err := dao.db.AutoMigrate(&model.User{})
	if err != nil {
		log.Fatalf("Failed to auto-migrate database: %v", err)
	}
	err = dao.db.Where("login_name = ?", user.LoginName).First(&existingUser).Error
	if err == nil {
		// 用户已存在
		return errors.New("account already exists")
	}

	// 对密码进行加密
	hashedPassword := md5.Sum([]byte(user.Password))

	user.Password = fmt.Sprintf("%x", hashedPassword)

	// 用户不存在，进行注册
	return dao.db.Create(user).Error
}

func (dao *GormUserDAO) Login(loginName, password string) (*model.User, string, error) {
	var user model.User
	err := dao.db.Where("login_name = ?", loginName).First(&user).Error
	if err != nil {
		return nil, "", err
	}

	// 对密码进行加密
	hashedPassword := md5.Sum([]byte(password))

	if user.Password != fmt.Sprintf("%x", hashedPassword) {
		return nil, "", errors.New("incorrect password")
	}

	// 生成token
	token, err := dao.GenerateToken(&user)
	if err != nil {
		return nil, "", err
	}

	fmt.Println("token:", token)
	return &user, token, nil
}

// 在 dao 层添加生成token的方法
func (dao *GormUserDAO) GenerateToken(user *model.User) (string, error) {
	// 创建JWT token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"user_id": user.ID,
		"exp":     time.Now().Add(time.Hour * 1).Unix(), // 1小时有效期
	})

	// 使用密钥签名token
	tokenString, err := token.SignedString([]byte("your-secret-key"))
	if err != nil {
		return "", err
	}
	// 将token存储到Redis中，设置过期时间
	err = dao.redis.Set(dao.ctx, tokenString, user.ID, time.Hour*1).Err()
	if err != nil {
		return "", err
	}
	log.Println("token已存入redis")
	return tokenString, nil
}

func (dao *GormUserDAO) ValidateToken(tokenString string) (uint, error) {
	// 从Redis中获取用户ID
	userIDStr, err := dao.redis.Get(dao.ctx, tokenString).Result()
	if err == redis.Nil {
		return 0, errors.New("token not found or expired")
	} else if err != nil {
		return 0, err
	}

	// 转换用户ID
	userID, err := strconv.ParseUint(userIDStr, 10, 32)
	if err != nil {
		return 0, err
	}

	return uint(userID), nil
}

func (dao *GormUserDAO) Close() error {
	if dao.redis != nil {
		return dao.redis.Close()
	}
	return nil
}
